package com.push.mq;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.IBinder;
import android.text.TextUtils;

import com.loyal.kit.DeviceUtil;
import com.loyal.kit.OutUtil;
import com.push.mq.impl.ServerImpl;

import org.eclipse.paho.android.service.MqttAndroidClient;
import org.eclipse.paho.client.mqttv3.IMqttActionListener;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;

public class MQPushService extends Service {
    private static final String TAG = "MQPush";

    private MqttAndroidClient client;
    private MqttConnectOptions conOpt;

    private static final String userName = "admin";
    private static final String passWord = "admin";
    private static String myTopic = "loyal";      //要订阅的主题
    private String clientId = DeviceUtil.deviceSerial();//"androidId";//客户端标识
    public MQPushService() {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        if (null == client)
            initMqtt();
    }

    private void initMqtt() {
        String mqIp = ServerImpl.serverUri;
        // 服务器地址（协议+地址+端口号）
        client = new MqttAndroidClient(getApplicationContext(),mqIp/* String.format("tcp://%s", mqIp)*//*host*/, clientId);
        // 设置MQTT监听并且接受消息
        client.setCallback(mqttCallback);
        conOpt = new MqttConnectOptions();
        //断开后，是否自动连接
        conOpt.setAutomaticReconnect(true);
        // 清除缓存
        //离线数据是否加载，这里不需要加载，只保持在线接收。
        conOpt.setCleanSession(true);
        // 设置超时时间，单位：秒
        conOpt.setConnectionTimeout(10);
        // 心跳包发送间隔，单位：秒   心跳时间，单位为秒。即多长时间确认一次Client端是否在线
        conOpt.setKeepAliveInterval(20);
        // 用户名
        conOpt.setUserName(userName);
        // 密码
        conOpt.setPassword(passWord.toCharArray());     //将字符串转换为字符串数组
        // last will message
        boolean doConnect = true;
        String message = "{\"terminal_uid\":\"" + clientId + "\"}";
        if (!TextUtils.isEmpty(message) || !TextUtils.isEmpty(myTopic)) {
            // 最后的遗嘱
            // MQTT本身就是为信号不稳定的网络设计的，所以难免一些客户端会无故的和Broker断开连接。
            //当客户端连接到Broker时，可以指定LWT，Broker会定期检测客户端是否有异常。
            //当客户端异常掉线时，Broker就往连接时指定的topic里推送当时指定的LWT消息。
            try {
                conOpt.setWill(myTopic, message.getBytes(), 1, false);
            } catch (Exception e) {
                e.printStackTrace();
                doConnect = false;
                iMqttActionListener.onFailure(null, e);
            }
        }
        if (doConnect) {
            doClientConnection();
        }
    }

    /**
     * 连接MQTT服务器
     */
    private void doClientConnection() {
        if (!client.isConnected() && isConnectIsNormal()) {
            try {
                client.connect(conOpt, null, iMqttActionListener);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }
    }

    // MQTT是否连接成功
    private IMqttActionListener iMqttActionListener = new IMqttActionListener() {

        @Override
        public void onSuccess(IMqttToken arg0) {
            try {
                // 订阅myTopic话题
                client.subscribe(myTopic, 1);
            } catch (MqttException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(IMqttToken arg0, Throwable cause) {
            OutUtil.println(TAG,"onFailure");
            try {
                cause.printStackTrace();
                // 连接失败，重连
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                reConnect();
            }
        }
    };

    // MQTT监听并且接受消息
    private MqttCallback mqttCallback = new MqttCallback() {

        @Override
        public void messageArrived(String topic, MqttMessage message) {
            String mqJson = new String(message.getPayload());
            OutUtil.println(TAG, "messageArrived:" + mqJson);
        }

        @Override
        public void deliveryComplete(IMqttDeliveryToken token) {
        }

        @Override
        public void connectionLost(Throwable cause) {
            OutUtil.println(TAG,"connectionLost");
            // 失去连接，重连
            try {
                if (null != cause)
                    cause.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                reConnect();
            }
        }
    };

    /*重新连接*/
    private void reConnect() {
        doClientConnection();
    }

    /**
     * 判断网络是否连接
     */
    private boolean isConnectIsNormal() {
        ConnectivityManager connectivityManager = (ConnectivityManager) getApplicationContext()
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (null == connectivityManager)
            return false;
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        return info != null && info.isAvailable();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onDestroy() {
        stopSelf();
        try {
            client.disconnect();
        } catch (MqttException e) {
            e.printStackTrace();
        }
        super.onDestroy();
    }
}